﻿using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics.Contracts;
using System.Dynamic;
using System.Linq;
using System.Text;

namespace UPNP.IO
{
    /// <summary>
    /// encapsulates values e.g. returned from an action invoke
    /// </summary>
    [System.Diagnostics.DebuggerStepThrough]
    public sealed class DynamicReturn : DynamicObject, IEnumerable<string>
    {
        public readonly static DynamicReturn Empty = new DynamicReturn();

        private readonly IDictionary<string, object> _values;

        public int Count
        {
            get { return _values.Count; }
        }

        public override bool TryGetMember(GetMemberBinder binder, out object result)
        {
            return _values.TryGetValue(binder.Name, out result);
        }

        public override bool TrySetMember(SetMemberBinder binder, object value)
        {
            if (!_values.Keys.Contains(binder.Name))
                return false;

            throw new InvalidOperationException("object is read-only");
        }

        public IEnumerator<string> GetEnumerator()
        {
            return _values.Keys.GetEnumerator();
        }

        IEnumerator IEnumerable.GetEnumerator()
        {
            return GetEnumerator();
        }

        public void Add(string key, object value)
        {
            Contract.Requires(!string.IsNullOrEmpty(key));

            _values.Add(key, value);
        }

        public object GetValue(string key)
        {
            Contract.Requires(!string.IsNullOrEmpty(key));

            return _values[key];
        }

        public DynamicReturn()
        {
            _values = new Dictionary<string, object>();
        }

        public DynamicReturn(IDictionary<string, object> values)
        {
            if (values == null)
                throw new ArgumentNullException("values");

            _values = values;
        }
    }
}
